/*
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! CHECKER      Test check store and load by value
//! RUN          options: "--no-async-jit --compiler-hotness-threshold=10 --compiler-regex _GLOBAL::test_value.*", entry: "_GLOBAL::func_main_0"
//! METHOD       "test_value_store_single_class"
//! PASS_BEFORE  "Lowering"
//! INST         "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST_NEXT    "CastAnyTypeValue"
//! INST_NEXT    /LoadObject.*Class/
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NEXT    "AnyTypeCheck ECMASCRIPT_INT_TYPE"
//! INST_NEXT    /LoadObject.*Elements/
//! INST_NEXT    "LenArray"
//! INST_NEXT    "BoundsCheck"
//! INST_NEXT    "StoreArray"
//! INST_NOT     "Intrinsic.StObjByValue"
//! METHOD       "test_value_load_single_class"
//! PASS_BEFORE  "Lowering"
//! INST         "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST_NEXT    "CastAnyTypeValue"
//! INST_NEXT    /LoadObject.*Class/
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NEXT    "AnyTypeCheck ECMASCRIPT_INT_TYPE"
//! INST_NEXT    /LoadObject.*Elements/
//! INST_NEXT    "LenArray"
//! INST_NEXT    "BoundsCheck"
//! INST_NEXT    "LoadArray"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NOT     "Intrinsic.LdObjByValue"
//! METHOD       "test_value_store_two_classes"
//! PASS_BEFORE  "Lowering"
//! INST         "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST_NEXT    "CastAnyTypeValue"
//! INST_NEXT    /LoadObject.*Class/
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "And"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NEXT    "AnyTypeCheck ECMASCRIPT_INT_TYPE"
//! INST_NEXT    /LoadObject.*Elements/
//! INST_NEXT    "LenArray"
//! INST_NEXT    "BoundsCheck"
//! INST_NEXT    "StoreArray"
//! INST_NOT     "Intrinsic.StObjByValue"
//! METHOD       "test_value_load_two_classes"
//! PASS_BEFORE  "Lowering"
//! INST         "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST_NEXT    "CastAnyTypeValue"
//! INST_NEXT    /LoadObject.*Class/
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "And"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NEXT    "AnyTypeCheck ECMASCRIPT_INT_TYPE"
//! INST_NEXT    /LoadObject.*Elements/
//! INST_NEXT    "LenArray"
//! INST_NEXT    "BoundsCheck"
//! INST_NEXT    "LoadArray"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NOT     "Intrinsic.LdObjByValue"
//! METHOD       "test_value_store_not_int"
//! PASS_BEFORE  "Lowering"
//! INST_NOT     "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST         "Intrinsic.StObjByValue"
//! METHOD       "test_value_load_not_int"
//! PASS_BEFORE  "Lowering"
//! INST_NOT     "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST         "Intrinsic.LdObjByValue"
//! METHOD       "test_value_store_key"
//! PASS_BEFORE  "Lowering"
//! INST         "LoadObjFromConst"
//! INST_NEXT    "Compare"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NEXT    "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST_NEXT    "CastAnyTypeValue"
//! INST_NEXT    /LoadObject.*Class/
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NOT     "Intrinsic.StObjByValue"
//! METHOD       "test_value_load_key"
//! PASS_BEFORE  "Lowering"
//! INST         "LoadObjFromConst"
//! INST_NEXT    "Compare"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NEXT    "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST_NEXT    "CastAnyTypeValue"
//! INST_NEXT    /LoadObject.*Class/
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NOT     "Intrinsic.LdObjByValue"
//! EVENT    /DeoptimizationReason,.*test_value_store_single_class.*ANY_TYPE_CHECK/
//! EVENT_NEXT    /DeoptimizationReason,.*test_value_load_single_class.*INLINE_IC/
//! EVENT_NEXT    /DeoptimizationReason,.*test_value_store_two_classes.*ANY_TYPE_CHECK/
//! METHOD       "test_value_store_with_update_length"
//! PASS_BEFORE  "Lowering"
//! INST         "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST_NEXT    "CastAnyTypeValue"
//! INST_NEXT    /LoadObject.*Class/
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NEXT    "AnyTypeCheck ECMASCRIPT_INT_TYPE"
//! INST_NEXT    /LoadObject.*Elements/
//! INST_NEXT    "LenArray"
//! INST_NEXT    "BoundsCheck"
//! INST_NEXT    /LoadObject.*Length/
//! INST_NEXT    "If"
//! INST_NEXT    "StoreArray"
//! INST_NOT     "Intrinsic.StObjByValue"


function test_value_store_single_class(a, b) {
    a[b] = 2
}

function test_value_load_single_class(a, b) {
    return a[b] + 1
}

function test_value_store_two_classes(a, b) {
    a[b] = 5
}

function test_value_load_two_classes(a, b) {
    return a[b]
}

function test_value_store_not_int(a, b) {
    a[b] = 6
}

function test_value_load_not_int(a, b) {
    return a[b] + 2
}

function test_value_store_key(a, b) {
    a[b] = 7
}

function test_value_load_key(a, b) {
    return a[b] + 3
}

function test_value_store_with_update_length(a, b) {
    a[b] = 9
}

let a = {}
let c = {}
let b1 = 1
let b2 = 2
let b3 = 3
c.field1 = 5
a[b1] = 30
a[b2] = 30
a[b3] = 30
c[b1] = 30
c[b2] = 30
c[b3] = 30
let d1 = Math.floor(1.2)
let d = {}
d[b1] = 30

let k = {}
let s = "key"

var array = [0]
for (var j = 0; j < 100; j++) {
    array[j] = j;
}
let b4 = 30

for (let i = 0 ; i < 50; i++) {
    test_value_store_single_class(a, b1)
    let res = test_value_load_single_class(a, b1)
    if ( res != 3) {
        throw "test_value_load_single_class is failed for b1 - incorrect return value: " + res;
    }
    test_value_store_single_class(a, b2)
    res = test_value_load_single_class(a, b2)
    if (res != 3) {
        throw "test_value_load_single_class is failed for b2 - incorrect return value: " + res;
    }
    test_value_store_single_class(a, b3)
    res = test_value_load_single_class(a, b3)
    if (res != 3) {
        throw "test_value_load_single_class is failed for b3 - incorrect return value: " + res;
    }
    test_value_store_two_classes(a, b1)
    res = test_value_load_two_classes(a, b1)
    if (res != 5) {
        throw "test_value_load_two_classes is failed for a and b1 - incorrect return value" + res;
    }
    test_value_store_two_classes(a, b2)
    res = test_value_load_two_classes(a, b2)
    if (res != 5) {
        throw "test_value_load_two_classes is failed for a and b2 - incorrect return value" + res;
    }
    test_value_store_two_classes(a, b3)
    res = test_value_load_two_classes(a, b3)
    if (res != 5) {
        throw "test_value_load_two_classes is failed for a and b3 - incorrect return value" + res;
    }
    test_value_store_two_classes(c, b1)
    res = test_value_load_two_classes(c, b1)
    if (res != 5) {
        throw "test_value_load_two_classes is failed for c and b1 - incorrect return value" + res;
    }
    test_value_store_two_classes(c, b2)
    res = test_value_load_two_classes(c, b2)
    if (res != 5) {
        throw "test_value_load_two_classes is failed for c and b2 - incorrect return value" + res;
    }
    test_value_store_two_classes(c, b3)
    res = test_value_load_two_classes(c, b3)
    if (res != 5) {
        throw "test_value_load_two_classes is failed for c and b3 - incorrect return value" + res;
    }
    test_value_store_not_int(a, d1)
    res = test_value_load_not_int(a, d1)
    if (res != 8) {
        throw "test_value_store_not_int is failed for  - incorrect return value: " + res;
    }
    test_value_store_key(k, s)
    res = test_value_load_key(k, s)
    if (res != 10) {
        throw "test_value_store_key is failed for  - incorrect return value: " + res;
    }
    array.length = 10
    test_value_store_with_update_length(array, b4)
    if (array.length  != 31) {
        throw "test_value_store_with_update_length is failed for  - incorrect lenth: " + array.length;
    }}

test_value_store_single_class(a, d1)
test_value_load_single_class(c, b1)

var get_type_error = false;
try {
    test_value_store_two_classes(10, b1)
} catch (e) {
    if (e instanceof TypeError) {
        get_type_error = true;
    }
}
if (!get_type_error) {
    throw "don't catch type error";
}